﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Web;
using System.Web.Hosting;
using System.Web.Security;
using System.Web.SessionState;
using System.Xml;
using System.Xml.Linq;
using EncryptHelper;
using WebHelper.Helpers;

namespace WebHelper.Modules
{
    [Serializable]
    public class SecurityModule : ConfigurationSection, IHttpModule
    {
        public static TimeSpan LicenceRemainingDays
        {
            get;
            private set;
        }
        public static bool LicenceUnlimited
        {
            get;set;
        }
        

        public static string Register(bool writeToWebConfig,string filePath)
        {
            if (string.IsNullOrEmpty(filePath))
            {
                filePath = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
            }
            XDocument document = XDocument.Load(filePath);
            XElement httpModules = XmlHelper.CreateIfNotExist(document.Root, "system.web", "httpModules");
            var configElement = httpModules.Elements("add").FirstOrDefault(e => e.Attribute("type").Value.Contains(typeof(SecurityModule).FullName));
            if (configElement!=null)
            {
                writeToWebConfig = false;
            }

            
            XElement modules = XmlHelper.CreateIfNotExist(document.Root, "system.webServer", "modules");
            configElement = modules.Elements("add").FirstOrDefault(e => e.Attribute("type") != null && e.Attribute("type").Value.Contains(typeof(SecurityModule).FullName));
            if (configElement!=null)
            {
                writeToWebConfig = false;
            }



            //configSection
            if (document.Element("configuration").Element("configSections") == null)
            {
                document.Element("configuration").AddFirst(new XElement("configSections"));
            }
            configElement = document.Element("configuration").Element("configSections").Elements("section").FirstOrDefault(e => e.Attribute("name").Value.Contains(typeof(SecurityModule).Name));
            if (configElement==null)
            {
                document.Element("configuration").Element("configSections").Add(new XElement("section",
                                                                                    new XAttribute("name", typeof(SecurityModule).Name),
                                                                                    new XAttribute("type", typeof(SecurityModule).FullName + "," + typeof(SecurityModule).Assembly.FullName)));
                //trace
                Trace.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + "registered the configsections", typeof(SecurityModule).Name + "  ");
            }

            //module section
            XElement SM = XmlHelper.CreateIfNotExist(document.Root, typeof(SecurityModule).Name);
            SM.SetAttributeValue("savedDataPath", "~/SM.data");
            SM.SetAttributeValue("encryptCookies", "false");
            SM.SetAttributeValue("encryptQueryString", "false");
            SM.SetAttributeValue("queryStringName", "EncrptedQueryString");
            SM.SetAttributeValue("noOfAuthenticatedUsers", "0");
            SM.SetAttributeValue("authenticatedUsersRedirectUrl", "");
            SM.SetAttributeValue("applicationLicencePath", "");
            SM.SetAttributeValue("licenceExpiredRedirectUrl", "");
            //trace
            Trace.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + "registered the module section", typeof(SecurityModule).Name + "  ");

             //protectedConfiguration
            XElement protectedConfiguration = XmlHelper.CreateIfNotExist(document.Root, "configProtectedData","providers");
            configElement = protectedConfiguration.Elements("add").FirstOrDefault(e => e.Attribute("type").Value.Contains(typeof(MyProtectedConfigurationProvider).FullName));
            if (configElement == null)
            {
                document.Element("configuration").Element("configProtectedData").Element("providers").Add(new XElement("add",
                                                                                    new XAttribute("name", typeof(MyProtectedConfigurationProvider).Name),
                                                                                    new XAttribute("type", typeof(MyProtectedConfigurationProvider).FullName + "," + typeof(MyProtectedConfigurationProvider).Assembly.FullName)));
            }

            //trace
            Trace.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + "registered protectedConfiguration section", typeof(SecurityModule).Name + "  ");
           
            
            //iis6
            configElement = httpModules.Elements("remove").FirstOrDefault(e => e.Attribute("name") != null && e.Attribute("name").Value.Contains(typeof(SecurityModule).FullName));
            if (configElement == null)
            {
                if (httpModules.Elements("remove").Count() > 0)
                {
                    httpModules.Elements("remove").Last().AddAfterSelf(new XElement("remove", new XAttribute("name", typeof(SecurityModule).FullName)));
                }
                else
                {
                    httpModules.AddFirst(new XElement("remove", new XAttribute("name", typeof(SecurityModule).FullName)));
                }
            }
            XElement element = new XElement("add",
                new XAttribute("name", typeof(SecurityModule).FullName),
                new XAttribute("type", typeof(SecurityModule).FullName + "," + typeof(SecurityModule).Assembly.FullName));
            httpModules.Add(element);
            
            //trace
            Trace.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + "registered in system.web", typeof(SecurityModule).Name + "  ");
            
            //iis 7
            configElement = modules.Elements("remove").FirstOrDefault(e => e.Attribute("name") != null && e.Attribute("name").Value.Contains(typeof(SecurityModule).FullName));
            if (configElement == null)
            {
                if (modules.Elements("remove").Count() > 0)
                {
                    modules.Elements("remove").Last().AddAfterSelf(new XElement("remove", new XAttribute("name", typeof(SecurityModule).FullName)));
                }
                else
                {
                    modules.AddFirst(new XElement("remove", new XAttribute("name", typeof(SecurityModule).FullName)));
                }
            }
            element = new XElement("add",
                new XAttribute("name", typeof(SecurityModule).FullName),
                new XAttribute("type", typeof(SecurityModule).FullName + "," + typeof(SecurityModule).Assembly.FullName),
                new XAttribute("preCondition","integratedMode"));
            modules.Add(element);
            
            //trace
            Trace.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + "registered in system.webServer", typeof(SecurityModule).Name + "  ");

            if (writeToWebConfig)
            {
                document.Save(filePath);

                //trace
                Trace.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + "registered and written at " + filePath, typeof(SecurityModule).Name + "  ");
            }
            return element.ToString();
        }
        public static void UnRegister(string filePath)
        {
            if (string.IsNullOrEmpty(filePath))
            {
                filePath = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
            }
            XDocument document = XDocument.Load(filePath);
            XElement configElement = null;
            XElement httpModules = XmlHelper.GetElementsOfPath(document.Root, "system.web", "httpModules").FirstOrDefault();
            if (httpModules != null)
            {
                configElement = httpModules.Elements("remove").FirstOrDefault(e => e.Attribute("name").Value.Contains(typeof(SecurityModule).FullName));
                if (configElement != null)
                {
                    configElement.Remove();
                }
                configElement = httpModules.Elements("add").FirstOrDefault(e => e.Attribute("type").Value.Contains(typeof(SecurityModule).FullName));
                if (configElement != null)
                {
                    configElement.Remove();
                }
            }
            XElement modules = XmlHelper.GetElementsOfPath(document.Root, "system.webServer", "modules").FirstOrDefault();
            if (modules != null)
            {
                configElement = modules.Elements("remove").FirstOrDefault(e => e.Attribute("name").Value.Contains(typeof(SecurityModule).FullName));
                if (configElement != null)
                {
                    configElement.Remove();
                }
                configElement = modules.Elements("add").FirstOrDefault(e => e.Attribute("type").Value.Contains(typeof(SecurityModule).FullName));
                if (configElement != null)
                {
                    configElement.Remove();
                }
            }
            XElement ConfigSections = XmlHelper.GetElementsOfPath(document.Root, "configSections", "section").FirstOrDefault(e => e.Attribute("type").Value.Contains(typeof(SecurityModule).FullName));
            if (ConfigSections != null)
            {
                ConfigSections.Remove();
                XElement SecurityModuleSection = XmlHelper.GetElementsOfPath(document.Root, ConfigSections.Attribute("name").Value).FirstOrDefault();
                if (SecurityModuleSection != null)
                {
                    SecurityModuleSection.Remove();
                }
            }
            XElement protectedConfiguration = XmlHelper.GetElementsOfPath(document.Root, "configProtectedData", "providers", "add").FirstOrDefault(e => e.Attribute("type").Value.Contains(typeof(MyProtectedConfigurationProvider).FullName));
            if (protectedConfiguration != null)
            {
                protectedConfiguration.Remove();
            }
            document.Save(filePath);

            //trace
            Trace.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + "unRegister from web.Congig", typeof(SecurityModule).Name + "  ");

        }
        public static void GenerateDataFile()
        {
            SecurityModule custSection = (SecurityModule)ConfigurationManager.GetSection(typeof(SecurityModule).Name);
            string dataPath = HostingEnvironment.MapPath(custSection.SavedDataPath);
            if (!File.Exists(dataPath))
            {
                using (MemoryStream mS = new MemoryStream())
                {
                    BinaryFormatter formatter = new BinaryFormatter();
                    formatter.Serialize(mS, new List<LicensesData>());
                    byte[] encryptedBytes = DefaultEncryptHelper.Encrypt(mS.ToArray(), WebHelper.Properties.Resources.Key);
                    File.WriteAllBytes(dataPath, encryptedBytes);

                    //trace
                    Trace.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + "create new dataPath File", typeof(SecurityModule).Name + "  ");

                }
            }
        }
        public static void EnableSslCookies(string filePath)
        {
            if (string.IsNullOrEmpty(filePath))
            {
                filePath = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
            }
            XDocument document = XDocument.Load(filePath);
            XElement httpCookies = XmlHelper.CreateIfNotExist(document.Root, "system.web", "httpCookies");
            httpCookies.SetAttributeValue("requireSSL", "true");
            document.Save(filePath);

            //trace
            Trace.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + "EnableSslCookies at " + filePath, typeof(SecurityModule).Name + "  ");
        }
        public static void DisableSslCookies(string filePath)
        {
            if (string.IsNullOrEmpty(filePath))
            {
                filePath = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
            }
            XDocument document = XDocument.Load(filePath);
            XElement httpCookies = XmlHelper.CreateIfNotExist(document.Root, "system.web", "httpCookies");
            httpCookies.SetAttributeValue("requireSSL", "false");
            document.Save(filePath);

            //trace
            Trace.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + "DisableSslCookies at " + filePath, typeof(SecurityModule).Name + "  ");
        }
        public static void EnableviewStateEncryption(string filePath)
        {
            if (string.IsNullOrEmpty(filePath))
            {
                filePath = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
            }
            XDocument document = XDocument.Load(filePath);
            XElement pages = XmlHelper.CreateIfNotExist(document.Root, "system.web", "pages ");
            pages.SetAttributeValue("ViewStateEncryptionMode", "Always");
            document.Save(filePath);

            //trace
            Trace.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + "EnableviewStateEncryption at " + filePath, typeof(SecurityModule).Name + "  ");
        }
        public static void DisableviewStateEncryption(string filePath)
        {
            if (string.IsNullOrEmpty(filePath))
            {
                filePath = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
            }
            XDocument document = XDocument.Load(filePath);
            XElement pages = XmlHelper.CreateIfNotExist(document.Root, "system.web", "pages ");
            pages.SetAttributeValue("ViewStateEncryptionMode", "Auto");
            document.Save(filePath);

            //trace
            Trace.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + "DisableviewStateEncryption at " + filePath, typeof(SecurityModule).Name + "  ");
        }
        public static void EncryptSection(string name, string filePath)
        {
            if (string.IsNullOrEmpty(filePath))
            {
                filePath = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
            }
            XDocument document = XDocument.Load(filePath);
            XElement sectionElement = XmlHelper.GetElementsOfPath(document.Root, name.Split('/')).FirstOrDefault();
            if (sectionElement != null)
            {
                if (sectionElement.Attribute("configProtectionProvider") == null || sectionElement.Attribute("configProtectionProvider").Value == "")
                {
                    string encryptedData = DefaultEncryptHelper.Encrypt(sectionElement.ToString(), WebHelper.Properties.Resources.Key);
                    sectionElement.RemoveAll();
                    sectionElement.SetAttributeValue("configProtectionProvider", "MyProtectedConfigurationProvider");
                    sectionElement.Add(XElement.Parse("<EncryptedData>" + HttpUtility.HtmlEncode(encryptedData) + "</EncryptedData>"));
                    document.Save(filePath);

                    //trace
                    Trace.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + "EncryptSection : " + name + " at " + filePath, typeof(SecurityModule).Name + "  ");
                }
            }
        }
        public static void DecryptSection(string name, string filePath)
        {
            if (string.IsNullOrEmpty(filePath))
            {
                filePath = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
            }
            XDocument document = XDocument.Load(filePath);
            XElement sectionElement = XmlHelper.GetElementsOfPath(document.Root, name.Split('/')).FirstOrDefault();
            if (sectionElement != null)
            {
                if (sectionElement.Attribute("configProtectionProvider") != null && sectionElement.Attribute("configProtectionProvider").Value == "MyProtectedConfigurationProvider")
                {
                    sectionElement.SetAttributeValue("configProtectionProvider", null);
                    XmlReader reader = sectionElement.Element("EncryptedData").CreateReader();
                    reader.MoveToContent();
                    string innerXml = reader.ReadInnerXml();

                    string decryptedData = DefaultEncryptHelper.Decrypt(HttpUtility.HtmlDecode(innerXml), WebHelper.Properties.Resources.Key);
                    XElement newElement=XElement.Parse(decryptedData);
                    sectionElement.AddBeforeSelf(newElement);
                    sectionElement.Remove();
                    document.Save(filePath);

                    //trace
                    Trace.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + "EncryptSection : " + name + " at " + filePath, typeof(SecurityModule).Name + "  ");
                }
            }

            //trace
            Trace.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + "DecryptSection : " + name + " at " + filePath, typeof(SecurityModule).Name + "  ");
        }
        public static void EncryptNeeded(string filePath)
        {
            SecurityModule.EncryptSection("appSettings",filePath);
            SecurityModule.EncryptSection("connectionStrings", filePath);
            SecurityModule.EncryptSection("system.net/mailSettings/smtp", filePath);
            SecurityModule.EncryptSection(typeof(SecurityModule).Name, filePath);

            //trace
            Trace.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + "EncryptNeeded at " + filePath, typeof(SecurityModule).Name + "  ");
        }
        public static void DecryptNeeded(string filePath)
        {
            SecurityModule.DecryptSection("appSettings", filePath);
            SecurityModule.DecryptSection("connectionStrings", filePath);
            SecurityModule.DecryptSection("system.net/mailSettings/smtp", filePath);
            SecurityModule.DecryptSection(typeof(SecurityModule).Name, filePath);

            //trace
            Trace.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + "DecryptNeeded at " + filePath, typeof(SecurityModule).Name + "  ");
        }

        [ConfigurationProperty("encryptCookies", IsRequired = true)]
        public bool EncryptCookies
        {
            get { return (bool)this["encryptCookies"]; }
            set { this["encryptCookies"] = value; }
        }

        [ConfigurationProperty("encryptQueryString", IsRequired = true)]
        public bool EncryptQueryString
        {
            get { return (bool)this["encryptQueryString"]; }
            set { this["encryptQueryString"] = value; }
        }

        [ConfigurationProperty("queryStringName", IsRequired = true)]
        public string QueryStringName
        {
            get { return this["queryStringName"].ToString(); }
            set { this["queryStringName"] = value; }
        }

        [ConfigurationProperty("noOfAuthenticatedUsers", IsRequired = true)]
        public int NoOfAuthenticatedUsers
        {
            get { return (int)this["noOfAuthenticatedUsers"]; }
            set { this["noOfAuthenticatedUsers"] = value; }
        }

        [ConfigurationProperty("authenticatedUsersRedirectUrl", IsRequired = true)]
        public string AuthenticatedUsersRedirectUrl
        {
            get { return (string)this["authenticatedUsersRedirectUrl"]; }
            set { this["authenticatedUsersRedirectUrl"] = value; }
        }

        [ConfigurationProperty("applicationLicencePath", IsRequired = true)]
        public string ApplicationLicencePath
        {
            get { return this["applicationLicencePath"].ToString(); }
            set { this["applicationLicencePath"] = value; }
        }

        [ConfigurationProperty("savedDataPath", IsRequired = true)]
        public string SavedDataPath
        {
            get { return this["savedDataPath"].ToString(); }
            set { this["savedDataPath"] = value; }
        }


        [ConfigurationProperty("licenceExpiredRedirectUrl", IsRequired = true)]
        public string LicenceExpiredRedirectUrl
        {
            get { return this["licenceExpiredRedirectUrl"].ToString(); }
            set { this["licenceExpiredRedirectUrl"] = value; }
        }

        public void Init(HttpApplication application)
        {
                SecurityModule custSection = (SecurityModule)ConfigurationManager.GetSection(typeof(SecurityModule).Name);
                
                
                this.EncryptCookies = custSection.EncryptCookies;
                this.EncryptQueryString = custSection.EncryptQueryString;
                this.QueryStringName = custSection.QueryStringName;
                this.NoOfAuthenticatedUsers = custSection.NoOfAuthenticatedUsers;
                this.AuthenticatedUsersRedirectUrl = custSection.AuthenticatedUsersRedirectUrl;
                this.ApplicationLicencePath = custSection.ApplicationLicencePath;
                this.LicenceExpiredRedirectUrl = custSection.LicenceExpiredRedirectUrl;
                this.SavedDataPath = custSection.SavedDataPath;




                application.BeginRequest += application_BeginRequest;
                application.AuthenticateRequest += application_AuthenticateRequest;

                application.PostReleaseRequestState += Application_PostReleaseRequestState;

                SessionStateModule session = (SessionStateModule)application.Modules["Session"];
                session.Start += session_Start;

                //trace
                try
                {
                    Trace.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + "Init", typeof(SecurityModule).Name + "  ");
                }
                catch
                {

                }

        }
        public void Dispose()
        {
            //clean-up code here.
            
            //trace
            Trace.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + "Dispose", typeof(SecurityModule).Name + "  ");
        }

        private void application_BeginRequest(object sender, EventArgs e)
        {
            //trace
            WebPageTraceListener wpListener = new WebPageTraceListener();
            if (Trace.Listeners.OfType<WebPageTraceListener>().Count() == 0)
            {
                Trace.Listeners.Add(wpListener);
            }


            //trace
            Trace.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + "application_BeginRequest ,EncryptCookies=" + this.EncryptCookies 
                + " ,EncryptQueryString=" + this.EncryptQueryString 
                + " ,QueryStringName=" + this.QueryStringName
                + " ,NoOfAuthenticatedUsers=" + this.NoOfAuthenticatedUsers
                + " ,AuthenticatedUsersRedirectUrl=" + this.AuthenticatedUsersRedirectUrl
                + " ,ApplicationLicencePath=" + this.ApplicationLicencePath
                + " ,LicenceExpiredRedirectUrl=" + this.LicenceExpiredRedirectUrl
                + " ,SavedDataPath=" + this.SavedDataPath
            , typeof(SecurityModule).Name + "  ");


            //cookies
            if (this.EncryptCookies)
            {
                HttpCookieCollection cookieCollection = HttpContext.Current.Request.Cookies;
                for (int i = 0; i < cookieCollection.Count; i++)
                {
                    HttpCookie cookie = cookieCollection[i];
                    try
                    {
                        if (cookie.Values["_Encrypted_"] == "1")
                        {
                            cookie.Values.Remove("_Encrypted_");

                            string encryptedCoocies = cookie.ToString();
                            
                            NameValueCollection encryptedvalues = new NameValueCollection(cookie.Values);
                            cookie.Values.Clear();
                            cookie.Values.Add(null, DefaultEncryptHelper.Decrypt(HttpUtility.UrlDecode(encryptedvalues[0]), WebHelper.Properties.Resources.Key));
                            for (int j = 1; j < encryptedvalues.Count; j++)
                            {
                                cookie.Values.Add(DefaultEncryptHelper.Decrypt(HttpUtility.UrlDecode(encryptedvalues.Keys[j]), WebHelper.Properties.Resources.Key), DefaultEncryptHelper.Decrypt(encryptedvalues[j], WebHelper.Properties.Resources.Key));
                            }
                            
                            //trace
                            Trace.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + "DecryptCookies :" + encryptedCoocies + "------>" + cookie.ToString(), typeof(SecurityModule).Name + "  ");
                        }
                    }
                    catch
                    {
                    }
                }
            }
            //query string
            if (this.EncryptQueryString)
            {
                string encryptedQuery = HttpContext.Current.Request.Url.Query;
                if (!string.IsNullOrEmpty(encryptedQuery))
                {
                    try
                    {
                        if (encryptedQuery.StartsWith("?" + this.QueryStringName + "="))
                        {
                            encryptedQuery = encryptedQuery.Substring(encryptedQuery.IndexOf("=") + 1);
                            int length = Convert.ToInt32(encryptedQuery.Substring(0, encryptedQuery.IndexOf("N")));
                            string acualEncryptedQuery = encryptedQuery.Substring(encryptedQuery.IndexOf("N") + 1, length);
                            string originalQueryString = HttpUtility.HtmlDecode(DefaultEncryptHelper.Decrypt(HttpUtility.UrlDecode(acualEncryptedQuery), WebHelper.Properties.Resources.Key));
                            HttpContext.Current.RewritePath(HttpContext.Current.Request.Url.AbsolutePath,"", originalQueryString+encryptedQuery.Substring(length.ToString().Length+length+1),false);
                            
                            //trace
                            Trace.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + "DecryptQuery :" + encryptedQuery + "------>" + originalQueryString, typeof(SecurityModule).Name + "  ");
                        }
                    }
                    catch
                    {
                    }
                }
            }
        }
        private void application_AuthenticateRequest(object sender, EventArgs e)
        {
            if (this.NoOfAuthenticatedUsers != 0 && Membership.GetNumberOfUsersOnline() > this.NoOfAuthenticatedUsers)
            {
                if (!string.IsNullOrEmpty(this.AuthenticatedUsersRedirectUrl))
                {
                    if (!HttpContext.Current.Request.Url.ToString().ToLower().Contains(UrlHelper.GetCompleteUri(this.AuthenticatedUsersRedirectUrl).ToLower()))
                    {
                        HttpContext.Current.Response.Redirect(this.AuthenticatedUsersRedirectUrl);

                        //trace
                        Trace.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + "Redirect The authenticated User", typeof(SecurityModule).Name + "  ");
                    }
                }
                else
                {
                    HttpContext.Current.Response.ClearContent();
                    HttpContext.Current.Response.Write("<h1 style=\"text-align:center;\">sorry ,but Number of Authenticated Users exceeded the maximum allowed for that site<br />please try again Later<h1>");
                    ((HttpApplication)sender).CompleteRequest();

                    //trace
                    Trace.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + "Show message to authenticated User", typeof(SecurityModule).Name + "  ");
                }
            }
        }
        private void Application_PostReleaseRequestState(object sender, EventArgs e)
        {
            //cookies
            if (this.EncryptCookies)
            {
                HttpCookieCollection cookieCollection = HttpContext.Current.Response.Cookies;
                for (int i = 0; i < cookieCollection.Count; i++)
                {
                    HttpCookie cookie = HttpContext.Current.Response.Cookies[i];

                    string origialCooieString = cookie.ToString();
                    try
                    {
                        NameValueCollection unencryptedValues = new NameValueCollection(cookie.Values);
                        cookie.Values.Clear();
                        cookie.Values.Add(null, HttpUtility.UrlEncode(DefaultEncryptHelper.Encrypt(unencryptedValues[0], WebHelper.Properties.Resources.Key)));
                        for (int j = 1; j < unencryptedValues.Count; j++)
                        {
                            cookie.Values.Add(HttpUtility.UrlEncode(DefaultEncryptHelper.Encrypt(unencryptedValues.Keys[j], WebHelper.Properties.Resources.Key)), HttpUtility.UrlEncode(DefaultEncryptHelper.Encrypt(unencryptedValues[j], WebHelper.Properties.Resources.Key)));
                        }
                        cookie.Values.Add("_Encrypted_", "1");

                        //trace
                        Trace.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + "EncryptCookies :" + origialCooieString + "------>" + cookie.ToString(), typeof(SecurityModule).Name + "  ");

                    }
                    catch
                    {
                    }
                }
            }

            //query string
            if (this.EncryptQueryString && HttpContext.Current.Response.ContentType.ToLower() == "text/HTML".ToLower())
            {
                HttpContext.Current.Response.Filter = new EncryptQueryStringFilter(HttpContext.Current.Response.Filter);
            }
        }
        private void session_Start(object sender, EventArgs e)
        {
            //licence
            if (!string.IsNullOrEmpty(this.ApplicationLicencePath))
            {
                try
                {
                    DateTime currentDate = DateTime.Now;

                    //licence
                    string licPath = HostingEnvironment.MapPath(this.ApplicationLicencePath);
                    byte[] LicBytes = File.ReadAllBytes(licPath);
                    byte[] decryptedLicBytes = DefaultEncryptHelper.Decrypt(LicBytes, WebHelper.Properties.Resources.Key);
                    BinaryFormatter formatter = new BinaryFormatter();
                    Dictionary<string, object> LicenceConfigrator = null;
                    using (MemoryStream mS = new MemoryStream(decryptedLicBytes))
                    {
                        LicenceConfigrator = (Dictionary<string, object>)formatter.Deserialize(mS);
                    }
                    bool unlimited = (bool)LicenceConfigrator["Unlimited"];
                    Guid id = (Guid)LicenceConfigrator["Id"];
                    int duration = (int)LicenceConfigrator["Duration"];

                    //trace
                    Trace.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + "licence unlimited=" + unlimited + " ,id=" + id + " ,duration=" + duration, typeof(SecurityModule).Name + "  ");

                    //data path
                    string dataPath = HostingEnvironment.MapPath(this.SavedDataPath);
                    byte[] dataBytes = File.ReadAllBytes(dataPath);
                    byte[] decrypteddataBytes = DefaultEncryptHelper.Decrypt(dataBytes, WebHelper.Properties.Resources.Key);
                    List<LicensesData> previousLicensesData = null;
                    using (MemoryStream mS = new MemoryStream(decrypteddataBytes))
                    {
                        previousLicensesData = (List<LicensesData>)formatter.Deserialize(mS);
                    }


                    var items = from i in previousLicensesData where i.ID == id select i;
                    LicensesData currentLicence = null;
                    if (items.Count() > 0)
                    {
                        currentLicence = items.First();

                        //trace
                        Trace.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + "licence found before :" + currentLicence.StartDate + " ------->" + currentLicence.EndDate, typeof(SecurityModule).Name + "  ");
                    }
                    else
                    {
                        currentLicence = new LicensesData();
                        currentLicence.ID = id;
                        currentLicence.StartDate = currentDate;
                        currentLicence.EndDate = currentLicence.StartDate.AddDays(duration);
                        previousLicensesData.Add(currentLicence);

                        //trace
                        Trace.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + "new Licence :" + currentLicence.StartDate + " ------->" + currentLicence.EndDate, typeof(SecurityModule).Name + "  ");
                    }

                    //check for licence
                    if (!unlimited)
                    {
                        if (currentDate < currentLicence.StartDate || currentDate > currentLicence.EndDate)
                        {
                            HttpContext.Current.Session.Abandon();
                            if (!string.IsNullOrEmpty(this.LicenceExpiredRedirectUrl))
                            {
                                if (!HttpContext.Current.Request.Url.ToString().ToLower().Contains(UrlHelper.GetCompleteUri(this.LicenceExpiredRedirectUrl).ToLower()))
                                {
                                    HttpContext.Current.Response.Redirect(LicenceExpiredRedirectUrl);


                                    //trace
                                    Trace.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + "Redirect for Licence expirations", typeof(SecurityModule).Name + "  ");
                                
                                }
                            }
                            else
                            {
                                HttpContext.Current.Response.ClearContent();
                                HttpContext.Current.Response.Write("<h1 style=\"text-align:center;\">sorry ,but your Licence has been expired <br /> please contact system Administartor to get new one<h1>");
                                HttpContext.Current.Response.End();

                                //trace
                                Trace.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + "message for Licence expirations", typeof(SecurityModule).Name + "  ");
                            }
                        }
                        else
                        {
                            //save last changes
                            using (MemoryStream mS = new MemoryStream())
                            {
                                currentLicence.StartDate = currentDate;
                                formatter.Serialize(mS, previousLicensesData);
                                byte[] encryptedBytes = DefaultEncryptHelper.Encrypt(mS.ToArray(), WebHelper.Properties.Resources.Key);
                                File.SetAttributes(dataPath, File.GetAttributes(dataPath) & ~FileAttributes.ReadOnly);
                                File.WriteAllBytes(dataPath, encryptedBytes);
                            }
                        }
                    }
                    SecurityModule.LicenceRemainingDays = currentLicence.EndDate - currentLicence.StartDate;
                    SecurityModule.LicenceUnlimited = unlimited;

                    //trace
                    Trace.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + "LicenceUnlimited" + unlimited + "LicenceRemainingDays =" + LicenceRemainingDays, typeof(SecurityModule).Name + "  ");
                }
                catch (Exception er)
                {

                    //trace
                    Trace.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + "Exception" + er.ToString(), typeof(SecurityModule).Name + "  ");

                    HttpContext.Current.Session.Abandon();
                    if (!string.IsNullOrEmpty(this.LicenceExpiredRedirectUrl))
                    {
                        if (!HttpContext.Current.Request.Url.ToString().ToLower().Contains(UrlHelper.GetCompleteUri(this.LicenceExpiredRedirectUrl).ToLower()))
                        {
                            HttpContext.Current.Response.Redirect(LicenceExpiredRedirectUrl);
                        }
                    }
                    else
                    {
                        HttpContext.Current.Response.ClearContent();
                        HttpContext.Current.Response.Write("<h1 style=\"text-align:center;\">sorry ,but your Licence has been expired <br /> please contact system Administartor to get new one<h1>");
                        HttpContext.Current.Response.End();
                    }
                }
            }
        }
        
        [Serializable]
        private class LicensesData
        {
            public Guid ID
            {
                get;
                set;
            }

            public DateTime StartDate
            {
                get;
                set;
            }

            public DateTime EndDate
            {
                get;
                set;
            }

        }
    }
}